<!DOCTYPE html>
<html lang="en">
	<head>
		<title>three.js webgl - interactive cubes</title>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
		<style>
			body {
				font-family: Monospace;
				background-color: #f0f0f0;
				margin: 0px;
				overflow: hidden;
			}
		</style>
	</head>
	<body>

		<script src="js/libs/jquery-1.6.4.js"></script>
		<script src="js/libs/three.js"></script>
		<script src="js/loaders/OBJLoader.js"></script>
		<script src="js/controls/TrackballControls.js"></script>
		
		<script>
			var camera, scene, renderer;
			//var controls;
			var mesh;
			var mouse = new THREE.Vector2();
			var projector = new THREE.Projector();
			var raycaster = new THREE.Raycaster();

			var INTERSECTED, SELECTED;

			var boxMesh,box;
			var planeMesh;
			
			var mouseDownX;
			var mouseDownY;
			
			var offset = new THREE.Vector3();
			
			var container;
			var controllers = [], plane;
			
			var table;
			var tableMeshPath = [6,7,3,2];
			var picture;
			var pictureMeshPath = [3, 6, 4, 1]; 
			
			var interactiveStep = 1;//1--define wall , floor and ceiling. 2--move content along some surface.
			
			var tablePathMesh;
			
				
			
			init();
			animate();

			function init() {
				container = document.createElement( 'div' );
				container.setAttribute("style", "background:url(assets/gallery01.jpg) no-repeat");
				document.body.appendChild( container );
				
				renderer = new THREE.WebGLRenderer();
				renderer.setSize( window.innerWidth, window.innerHeight );
				container.appendChild( renderer.domElement );

				camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
				camera.position.z = 400;

				scene = new THREE.Scene();

				var light = new THREE.DirectionalLight( 0xffffff, 2 );
				light.position.set( 1, 1, 1 ).normalize();
				light.name = "light1";
				scene.add( light );

				var light = new THREE.DirectionalLight( 0xffffff );
				light.position.set( -1, -1, -1 ).normalize();
				light.name = "light2";
				scene.add( light );

				/*controls = new THREE.TrackballControls( camera );
				controls.rotateSpeed = 1.0;
				controls.zoomSpeed = 1.2;
				controls.panSpeed = 0.8;
				controls.noZoom = false;
				controls.noPan = false;
				controls.staticMoving = true;
				controls.dynamicDampingFactor = 0.3;*/
				
				

				box = new THREE.CubeGeometry(300,300,300,1,1,1);
				box.dynamic = true;
				
				var boxMat = new THREE.MeshBasicMaterial({wireframe: true, color:0xff0000});
				boxMesh = new THREE.Mesh(box, boxMat);
				boxMesh.geometry.verticesNeedUpdate=true;
				boxMesh.geometry.dynamic = true;
				boxMesh.name="boxMesh";
				scene.add(boxMesh);

				for(var i=0; i<box.vertices.length; i++){
					var controlBox = new THREE.CubeGeometry(10,10,10,1,1,1);
					var controlBoxMat = new THREE.MeshBasicMaterial({color:0x00ff00});
					var controlBoxMesh = new THREE.Mesh(controlBox, controlBoxMat);
					controlBoxMesh.name = "control" + i.toString();
					scene.add(controlBoxMesh);
					var vector = box.vertices[i];
					controlBoxMesh.position.x = vector.x;
					controlBoxMesh.position.y = vector.y;
					controlBoxMesh.position.z = vector.z;
					
					//what about controller only move on xoy plane
					//why not keep the same with the demo?
					controllers.push( controlBoxMesh );
				}
				
				plane = new THREE.Mesh( new THREE.PlaneGeometry( 2000, 2000, 8, 8 ), new THREE.MeshBasicMaterial( { color: 0x000000, opacity: 0.25, transparent: true, wireframe: true } ) );
				plane.visible = false;
				plane.name = "eightControllerPathPanel";
				scene.add( plane );

				window.addEventListener( 'resize', onWindowResize, false );
				renderer.domElement.addEventListener( 'mousemove', onDocumentMouseMove, false );
				renderer.domElement.addEventListener( 'mousedown', onDocumentMouseDown, false );
				renderer.domElement.addEventListener( 'mouseup', onDocumentMouseUp, false );
				document.addEventListener('keydown', onDocumentKeyDown, false);
				
				table = loadObj("3"); //7632
				//picture = loadObj("1");//3641
			}
			
			var r = 0;
			function onDocumentKeyDown(event){
				table = scene.getObjectByName("content3");
				var step = 5;

				switch( event.keyCode ) {
					case 65:{//a
						interactiveStep = 2;
						var tableGeo = new THREE.PlaneGeometry( 2000, 2000, 1, 1 );
						tablePathMesh = new THREE.Mesh(tableGeo , 
											new THREE.MeshBasicMaterial( { color: 0xff0000,wireframe: true } ) );
						for(var i=0; i<tableGeo.vertices.length; i++){
							tablePathMesh.geometry.vertices[i].x = controllers[tableMeshPath[i]].position.x;
							tablePathMesh.geometry.vertices[i].y = controllers[tableMeshPath[i]].position.y;
							tablePathMesh.geometry.vertices[i].z = controllers[tableMeshPath[i]].position.z;
						}
						tablePathMesh.geometry.dynamic = true;
						tablePathMesh.geometry.verticesNeedUpdate=true;
						tablePathMesh.geometry.elementsNeedUpdate=true;
						tablePathMesh.geometry.buffersNeedUpdate=true;
						tablePathMesh.name="tablePathMesh";
						scene.add( tablePathMesh );
						
						scene.remove(scene.getObjectByName("boxMesh"));
						scene.remove(scene.getObjectByName("eightControllerPathPanel"));
						for(var j=0; j<controllers.length; j++){
							scene.remove(controllers[j]);
						}
						break;
					}
					

					case 37:{//left
						console.log("left");
						table.position.x += step;
						break;
					}case 38:{//up
						console.log("up");
						table.position.z += step;
						break;
					}case 39:{//right
						console.log("right");
						table.position.x -= step;
						break;
					}case 40:{//down
						console.log("down");
						table.position.z -= step;
						break;
					}case 69:{//e
						table.position.y += step;
						break;
					}case 81:{//q
						table.position.y -= step;
						break;
					}case 82:{//r
						r+=step;
						table.rotation.setY(r);
						break;
					}
					
				
				}
			}
			
			
			function loadObj(id){
				var texture = new THREE.Texture();
			
				var loader = new THREE.ImageLoader();
				loader.addEventListener( 'load', function ( event ) {
					texture.image = event.content;
					texture.needsUpdate = true;
				});
				loader.load( 'assets/' + id + '/' + id + '.png' );

				// model

				var loader = new THREE.OBJLoader();
				loader.addEventListener( 'load', function ( event ) {

					var object = event.content;

					object.traverse( function ( child ) {
						if ( child instanceof THREE.Mesh ) {
							child.material.map = texture;
							content = child;
						}
					} );
					object.position.y = - 160;
					scene.add( object );
					object.name = "content"+id;
					return object; 
				}
					
				);
				loader.load( 'assets/' + id + '/' + id + '.obj');
			}
			
			
			
			
			var SELECTED;
			var INTERSECTED;
			function onDocumentMouseMove( event ) {

				event.preventDefault();

				mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
				mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;

				//

				var vector = new THREE.Vector3( mouse.x, mouse.y, 0.5 );
				projector.unprojectVector( vector, camera );

				var raycaster = new THREE.Raycaster( camera.position, 
					vector.sub( camera.position ).normalize() );
					
				//why table path mesh cannot be selected?
				var intersects = raycaster.intersectObjects( scene.children );
				for(var j = 0; j<intersects.length; j++){
					console.log(intersects[j].object.name);
				}

				if(interactiveStep == 1){
					
					if ( SELECTED ) {
						
						var intersects = raycaster.intersectObject( plane );
						SELECTED.position.copy( intersects[ 0 ].point.sub( offset ) );
						
						var tempName = SELECTED.name;
						var controlStr  = "control";
						var index = tempName.substring(controlStr.length, tempName.length);
						boxMesh.geometry.vertices[index].x = SELECTED.position.x;
						boxMesh.geometry.vertices[index].y = SELECTED.position.y;
						boxMesh.geometry.vertices[index].z = SELECTED.position.z;
						
						console.log(index);
						return;
					}


					var intersects = raycaster.intersectObjects( controllers );

					if ( intersects.length > 0 ) {

						if ( INTERSECTED != intersects[ 0 ].object ) {

							if ( INTERSECTED ) INTERSECTED.material.color.setHex( INTERSECTED.currentHex );

							INTERSECTED = intersects[ 0 ].object;
							INTERSECTED.currentHex = INTERSECTED.material.color.getHex();

							plane.position.copy( INTERSECTED.position );
							plane.lookAt( camera.position );

						}
					} else {
						if ( INTERSECTED ) INTERSECTED.material.color.setHex( INTERSECTED.currentHex );
						INTERSECTED = null;
					}
				}
				else if(interactiveStep == 2){
					if ( SELECTED ) {
						var intersects = raycaster.intersectObjects( scene.children, true );
						
						
						for(var i=0; i<intersects.length; i++){
							if(intersects[i].object.name == "tablePathMesh"){
								SELECTED.position.copy( intersects[ 0 ].point);
							}
						}
						
						return;
					}
				}
			}

			function onDocumentMouseDown( event ) {
				event.preventDefault();

				var vector = new THREE.Vector3( mouse.x, mouse.y, 0.5 );
				projector.unprojectVector( vector, camera );

				var raycaster = new THREE.Raycaster( camera.position, 
					vector.sub( camera.position ).normalize() );

				if(interactiveStep == 1){
					var intersects = raycaster.intersectObjects( controllers );

					if ( intersects.length > 0 ) {

						//controls.enabled = false;

						SELECTED = intersects[ 0 ].object;

						var intersects = raycaster.intersectObject( plane );
						offset.copy( intersects[ 0 ].point ).sub( plane.position );
					}
				}else if(interactiveStep == 2){
					var intersects = raycaster.intersectObjects( scene.children, true);

					for(var i=0; i<intersects.length; i++){
						if(intersects[i].object.name.indexOf("Object")!=-1)
							SELECTED = intersects[i].object;
					}
				}
				

			}

			function onDocumentMouseUp( event ) {
				event.preventDefault();
				//controls.enabled = true;
				if ( INTERSECTED ) {
					plane.position.copy( INTERSECTED.position );
					SELECTED = null;
				}
			}
			
			
			
			
			
			
			
			
			
			
			
			function onWindowResize() {

				camera.aspect = window.innerWidth / window.innerHeight;
				camera.updateProjectionMatrix();

				renderer.setSize( window.innerWidth, window.innerHeight );

			}

			function animate() {
				if(boxMesh!=null)
					boxMesh.geometry.verticesNeedUpdate=true;
				if(tablePathMesh!=null){
					for(var i=0; i<tablePathMesh.geometry.vertices.length; i++){
						tablePathMesh.geometry.vertices[i].x = controllers[tableMeshPath[i]].position.x;
						tablePathMesh.geometry.vertices[i].y = controllers[tableMeshPath[i]].position.y;
						tablePathMesh.geometry.vertices[i].z = controllers[tableMeshPath[i]].position.z;
					}
						
					tablePathMesh.geometry.elementsNeedUpdate=true;
					tablePathMesh.geometry.verticesNeedUpdate=true;
					tablePathMesh.buffersNeedUpdate = true;
				}
				
				
					
					
					
				requestAnimationFrame( animate );
				renderer.render( scene, camera );
				//controls.update();
				
				
			}
			

		</script>
	</body>
</html>
